package com.feature50.clarity.components;

import com.feature50.clarity.misc.ClarityProgressMonitor;
import com.feature50.clarity.misc.SimpleClarityProgressMonitor;
import com.jgoodies.forms.layout.Sizes;

import javax.swing.JComponent;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.lang.ref.WeakReference;

/**
 * Designed for use with a {@link com.feature50.clarity.FormContainer}, DisablePanel is set as the glass pane of
 * the FormContainer's {@link javax.swing.JRootPane}.
 */
public class DisablePanel extends JComponent {
    private static final String DEFAULT_MESSAGE = "Please Wait...";
    private WeakReference<SimpleClarityProgressMonitor> monitor;

    private static final int MIN_WIDTH = 100;
    private static final int MIN_HEIGHT = 50;
    private static final int PADDING_X = 10;
    private static final int PADDING_Y = 10;

    public DisablePanel(SimpleClarityProgressMonitor monitor) {
        this.monitor = new WeakReference<SimpleClarityProgressMonitor>(monitor);
        setOpaque(false);
        setFont(new Font("Arial", Font.PLAIN, 16));

        addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent e) {
                e.consume();
            }

            public void mousePressed(MouseEvent e) {
                e.consume();
            }

            public void mouseReleased(MouseEvent e) {
                e.consume();
            }

            public void mouseEntered(MouseEvent e) {
                e.consume();
            }

            public void mouseExited(MouseEvent e) {
                e.consume();
            }
        });

        addMouseMotionListener(new MouseMotionListener() {
            public void mouseDragged(MouseEvent e) {
                e.consume();
            }

            public void mouseMoved(MouseEvent e) {
                e.consume();
            }
        });

        addMouseWheelListener(new MouseWheelListener() {
            public void mouseWheelMoved(MouseWheelEvent e) {
                e.consume();
            }
        });
    }

    public ClarityProgressMonitor getMonitor() {
        return monitor.get();
    }

    public void setMonitor(SimpleClarityProgressMonitor monitor) {
        this.monitor = new WeakReference<SimpleClarityProgressMonitor>(monitor);
    }

    private String getMessage() {
        SimpleClarityProgressMonitor mon = monitor.get();
        String msg = null;
        if (mon != null) {
            msg = mon.getCaption();
        }

        if (msg == null) msg = DEFAULT_MESSAGE;
        return msg;
    }

    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        int x = 0;
        int y = 0;
        int w = getSize().width;
        int h = getSize().height;

        g2d.setColor(new Color(0, 0, 0, 128));
        g2d.fillRect(0, 0, w, h);

        String msg = getMessage();
        int mw = g2d.getFontMetrics().stringWidth(msg);
        int mh = g2d.getFontMetrics().getAscent();

        int dw = Math.max(mw + Sizes.dialogUnitXAsPixel(PADDING_X, this), Sizes.dialogUnitXAsPixel(MIN_WIDTH, this));
        int dh = Math.max(mh + Sizes.dialogUnitYAsPixel(PADDING_Y, this), Sizes.dialogUnitYAsPixel(MIN_HEIGHT, this));
        int dx = (w / 2) - (dw / 2) + x;
        int dy = (h / 2) - (dh / 2) + y;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.BLACK);
        g2d.fillRoundRect(dx, dy, dw, dh, 10, 10);
        g2d.setColor(Color.WHITE);
        g2d.setStroke(new BasicStroke(3));
        g2d.drawRoundRect(dx, dy, dw, dh, 10, 10);

        int mx = (dw / 2) - (mw / 2) + dx;
        int my = (dh / 2) + (mh / 2) + dy;

        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setColor(Color.WHITE);
        g2d.drawString(msg, mx, my);

        g2d.dispose();
    }
}
